/*
 * @Author: ygnnli 1585923072@qq.com
 * @Date: 2024-08-14 15:06:28
 * @LastEditors: ygnnli 1585923072@qq.com
 * @LastEditTime: 2024-08-27 23:26:11
 * @FilePath: /bitrpc/source/detail.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once
#include <cstdio>
#include <ctime>
#include <iostream>
#include <string>
#include <memory>
#include <random>
#include <sstream>
#include <atomic>
#include <iomanip>
#include <jsoncpp/json/json.h>

namespace bitrpc
{
// 日志等级
#define LDBG 0
#define LINF 1
#define LERR 2

// 日志等级默认值
#define LDEFAULT LDBG
// 日志宏  //strfitime:将时间格式化成字符串
#define LOG(level, format, ...)                                                                       \
    {                                                                                                 \
        if (level >= LDEFAULT)                                                                        \
        {                                                                                             \
            time_t t = time(NULL);                                                                    \
            struct tm *lt = localtime(&t);                                                            \
            char time_tmp[32] = {0};                                                                  \
            strftime(time_tmp, 31, "%Y-%m-%d %T", lt);                                                \
            fprintf(stdout, "[%s][%s:%d] " format "\n", time_tmp, __FILE__, __LINE__, ##__VA_ARGS__); \
        }                                                                                             \
    }

// 不同等级的日志宏
#define DLOG(format, ...) LOG(LDBG, format, ##__VA_ARGS__)
#define ILOG(format, ...) LOG(LINF, format, ##__VA_ARGS__)
#define ELOG(format, ...) LOG(LERR, format, ##__VA_ARGS__)

    class JSON
    {
    public:
        // 实现数据的序列化
        static bool serialize(const Json::Value &val, std::string &body)
        {
            std::stringstream ss;
            // 先实例化一个工厂类对象
            Json::StreamWriterBuilder swb;
            // 通过工厂类对象来生产派生类对象
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            int ret = sw->write(val, &ss); // 将val序列化到ss中
            if (ret != 0)
            {
                ELOG("json serialize failed! ");
                return false;
            }
            body = ss.str();
            return true;
        }

        // 实现json字符串的反序列化
        static bool unserialize(const std::string &body, Json::Value &val)
        {
            // 实例化工厂类对象
            Json::CharReaderBuilder crb;
            // 生产CharReader对象
            std::string errs;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs); // errs为错误信息
            if (ret == false)
            {
                ELOG("json unserialize failed: %s ", errs.c_str());
                return false;
            }
            return true;
        }
    };

    class UUID
    {
    public:
        static std::string uuid()
        {
            std::stringstream ss; // 定义一个stringstream对象
            // 1.构造一个机器随机对象
            std::random_device rd; // random_device:通过硬件生成一个随机数种子对象
            // 2.以机器随机数种子构造伪随机数对象
            std::mt19937 generator(rd()); // 伪随机数生成器
            // 3.构造限定数据范围的对象
            std::uniform_int_distribution<int> distribution(0, 255); // 限制随机数范围
            // 4.生成8个随机数，按特定格式组织成为16进制数字字符的字符串
            for (int i = 0; i < 8; i++)
            {
                if (i == 4 || i == 6) // 02 03 ef 1d - 47 ac - e7 c8
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator); // setw:设置输出宽度，setfill:设置不足2位的填充字符，hex:以16进制输出
            }
            ss << "-";
            // 5. 定义⼀个8字节序号，逐字节组织成为16进制数字字符的字符串
            static std::atomic<size_t> seq(1); // 定义一个原子变量，用于生成唯一ID size_t:32位是4字节，64位是8字节
            size_t cur = seq.fetch_add(1);     // 获取当前值，并自增1
            for (int i = 7; i >= 0; i--)       // 00 00 00 00 00 00 00 01 从前往后获得
            {
                if (i == 5) // 00 00 - 00 00 00 00 00 01
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> (i * 8)) & 0xFF); // 将当前值转换为16进制，并按位取出每一个字节
            }
            return ss.str(); // 输出结果
        }
    };
}